﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

namespace DataGeneration.Domain.Helpers
{
    /// <summary>
    /// Defines the type XElementExtender
    /// </summary>
    public static class XElementExtender
    {
        /// <summary>
        /// Determines whether the specified element contains attribute.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <returns>
        /// 	<c>true</c> if the specified element contains attribute; otherwise, <c>false</c>.
        /// </returns>
        public static bool ContainsAttribute(this XElement element, string attributeName)
        {
            return element.Attribute(attributeName) != null;
        }

        /// <summary>
        /// Determines whether [contains attribute with value] [the specified element].
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <param name="attributeValue">The attribute value.</param>
        /// <returns>
        /// 	<c>true</c> if [contains attribute with value] [the specified element]; otherwise, <c>false</c>.
        /// </returns>
        public static bool ContainsAttributeWithValue(this XElement element, string attributeName, string attributeValue)
        {
            return element.Attribute(attributeName) != null && element.Attribute(attributeName).Value.Trim().Equals(attributeValue);
        }
        /// <summary>
        /// Determines whether [contains attribute without value] [the specified element].
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <param name="attributeValue">The attribute value.</param>
        /// <returns>
        /// 	<c>true</c> if [contains attribute without value] [the specified element]; otherwise, <c>false</c>.
        /// </returns>
        public static bool ContainsAttributeWithoutValue(this XElement element, string attributeName, string attributeValue)
        {
            return element.Attribute(attributeName) != null && !element.Attribute(attributeName).Value.Trim().Equals(attributeValue);
        }

        /// <summary>
        /// Reads the attribute value.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <returns></returns>
        public static string ReadAttributeValue(this XElement element, string attributeName)
        {
            if (!element.ContainsAttribute(attributeName))
            {
                throw new Exception(string.Format("{0} does not have an attribute with name: {1}!", element.Name.LocalName, attributeName));
            }

            return element.Attribute(attributeName).Value;
        }

        /// <summary>
        /// Uns the safe read attribute value.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <returns></returns>
        public static string UnSafeReadAttributeValue(this XElement element, string attributeName)
        {
            return element.Attribute(attributeName).Value;
        }

        /// <summary>
        /// Retrieves the child elements containing attributes.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="elementName">Name of the element.</param>
        /// <returns></returns>
        public static IEnumerable<XElement> RetrieveChildElementsMatchingElementName(this XContainer container, string elementName)
        {
            return from items in container.Descendants()
                   where items.LocalName().Equals(elementName)
                   select items;
        }

        /// <summary>
        /// Retrieves the entity.
        /// </summary>
        /// <param name="container">The container.</param>
        /// <param name="attributeName">Name of the attribute.</param>
        /// <param name="attributeValue">The attribute value.</param>
        /// <returns></returns>
        public static XElement RetrieveEntity(this XContainer container,string attributeValue)
        {
           return  (from items in container.Descendants()
                   where items.LocalName().Equals(Tokens.Entity) &&
                         items.ContainsAttributeWithValue(Tokens.EntityName,attributeValue)
                   select items).First();
        }

        /// <summary>
        /// Locals the name.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        public static string LocalName(this XElement element)
        {
            return element.Name.LocalName;
        }
    }
}


